
#include <cstdlib>
#include <iostream>
#include <istream>
#include <fstream>
#include <string>
#include <cstring>
#include <exception>
#include "Input.h"
#include "Output.h"
#include "Grafico.h"
#include "Figura.h"
#include "FiguraFactory.h"
#include "Lista.h"
#include "DescriptorReader.h"

using namespace std;
using namespace TP;
using namespace TP::Grafica;
using namespace TP::Grafica::Componentes;
using namespace TP::Colecciones;

//==============================================================================

#define EXIT_SUCCESS 0

//==============================================================================

int main(int argc, char *argv[])
{
    // Inicializo le flag de ejecucion.
    int exec_stat = EXIT_SUCCESS;

    // Se declara la entrada y slidad de datos.
    Input input (argc, argv);
    Output output (argc, argv);
    DescriptorReader reader;
    
    try
    {
        // Inicializo la entrada de datos.
        input.Inicializar();
        
        // Inicializo la salida de datos.
        output.Inicializar();
    
        // Inicializo las entidades que soportan el grafico.  Leo de la entrada de 
        // datos los descriptores de componentes en forma secuencial.  Los instancio
        // mediante la factory y guardo una referencia al mismo para su posterior
        // destruccion.

        Lista figuras;
        FiguraFactory factory;

        while (!input.Stream().eof())
        {
           input.Stream() >> reader;
           Figura* aux = factory.crear(reader.Descripor());
           figuras.Agregar(aux);
        }

        // Construyo el grafico a partir de las figuras instanciadas.
        Grafico grafico;
        IGraficable* cursor = (IGraficable*) figuras.Primero();

        while (NULL != cursor)
        {
           grafico.addGraficable(cursor);
           cursor = (IGraficable*) figuras.Siguiente(cursor);
        }

        // Renderizo el grafico en formato BMP sobre output.
        BMP* bmp = grafico.toBMP();
        output.Stream() << (*bmp);
        delete bmp;

        // Elimino las figuras instanciadas.
        while (!figuras.Vacia())
        {
           // Extraigo la primer figura de la coleccion.
           Figura* figura = (Figura*)figuras.Remover(figuras.Primero());
           delete figura;
        }
      
    }
    catch (FiguraFactoryException& pEx)
    {
        cerr << pEx.what();
    }
    catch (int& pEx)
    {
        exec_stat = pEx;
    }
       
    return exec_stat;
}

// =============================================================================
